package dproxy.server.net.protocol;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import dproxy.server.common.exceptions.AppInfrastructureException;
import dproxy.server.common.exceptions.ResponseReadException;
import dproxy.server.net.backoff.Timeout;

/**
 * Multi-purpose Protocol. 
 * This class was created for testing purposes and should not
 * be used on production
 */
public class GenericProtocol extends BaseProtocol {

    /** Stream buffer lenght. */
    private static final int READ_BUFFER_SIZE = 512;

    /** Logger. */
    private Log logger = LogFactory.getLog(getClass());
    
    /**
     * @see dproxy.server.net.protocol.Protocol#getName()
     */
    public String getName() {
        return "Generic";
    }

    /**
     * @see dproxy.server.net.protocol.BaseProtocol#init()
     */
    @Override
    public void init() {
        super.init();
        if (logger.isDebugEnabled()) {
            logger.debug("Initiating Generic Protocol");
        }
    }

    /**
     * @see dproxy.server.net.protocol.Protocol#generateKey(byte[])
     */
    public String generateKey(byte[] request) {
        return createSimpleKey(request);
    }

    /**
     * @see dproxy.server.net.protocol.Protocol#readRequest(InputStream)
     */
    public byte[] readRequest(InputStream inputStream) {
        byte[] bs;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            while (true) {
                // Read a set of characters from the socket
                int i;
                byte[] buffer = new byte[READ_BUFFER_SIZE];
                i = inputStream.read(buffer);
                for (int j=0; j<i; j++) {
                    baos.write((byte)buffer[j]);
                }
                if (inputStream.available() == 0) {
                    break;
                }
            }
        } catch (IOException e) {
            throw new AppInfrastructureException(e);
        }
        bs = baos.toByteArray();
        return bs;
    }

    /**
     * @see dproxy.server.net.protocol.Protocol#readResponse(InputStream)
     */
    public byte[] readResponse(InputStream inputStream)
            throws ResponseReadException {
        byte[] bs;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            while (true) {
                // Read a set of characters from the socket
                int i;
                byte[] buffer = new byte[READ_BUFFER_SIZE];
                i = inputStream.read(buffer);
                for (int j=0; j<i; j++) {
                    baos.write((byte)buffer[j]);
                }
                if (inputStream.available() == 0) {
                    Timeout.getInstance().waitForDataAvailable(inputStream);
                    if (inputStream.available() == 0) {
                    	break;
                    }
                }
            }
        } catch (IOException e) {
            throw new AppInfrastructureException(e);
        }
        bs = baos.toByteArray();
        return bs;
    }
    
}
